package com.cc.blog.web.service.impl;

import com.cc.blog.admin.domain.vo.FindWikiCatalogListRspVO;
import com.cc.blog.admin.domain.vo.FindWikiListRspVO;
import com.cc.blog.admin.mapper.WikiCatalogMapper;
import com.cc.blog.admin.mapper.WikiMapper;
import com.cc.blog.admin.model.WikiCatalogDO;
import com.cc.blog.admin.model.WikiDO;
import com.cc.blog.common.enums.WikiCatalogLevelEnum;
import com.cc.blog.common.utils.Result;
import com.cc.blog.web.domain.dto.FindWikiArticlePreNextReqDTO;
import com.cc.blog.web.domain.dto.FindWikiCatalogListReqDTO;
import com.cc.blog.web.domain.vo.FindPreNextArticleRspVO;
import com.cc.blog.web.domain.vo.FindWikiArticlePreNextRspVO;
import com.cc.blog.web.service.WikiService;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Author cc
 * @Date 2025/1/13 10:34
 */
@Service
@Slf4j
@AllArgsConstructor
public class WikiServiceImpl implements WikiService {

    private final WikiMapper wikiMapper;
    private final WikiCatalogMapper wikiCatalogMapper;

    @Override
    public Result findWikiList() {
        // 查询已发布的知识库
        List<WikiDO> wikiDOS = wikiMapper.selectPublished();
        // DO 转 VO
        List<FindWikiListRspVO> vos = null;
        if (!CollectionUtils.isEmpty(wikiDOS)) {
            vos = wikiDOS.stream()
                    .map(wikiDO -> FindWikiListRspVO.builder()
                            .id(wikiDO.getId())
                            .title(wikiDO.getTitle())
                            .cover(wikiDO.getCover())
                            .summary(wikiDO.getSummary())
                            .isTop(wikiDO.getWeight() > 0)
                            .build())
                    .collect(Collectors.toList());
            // 设置每个知识库的第一篇文章 ID，方便前端跳转
            vos.forEach(vo -> {
                Long wikiId = vo.getId();
                WikiCatalogDO wikiCatalogDO = wikiCatalogMapper.selectFirstArticleId(wikiId);
                vo.setFirstArticleId(Objects.nonNull(wikiCatalogDO) ? wikiCatalogDO.getArticleId() : null);
            });
        }
        return Result.success(vos);
    }

    @Override
    public Result findWikiCatalogList(FindWikiCatalogListReqDTO findWikiCatalogListReqDTO) {
        Long wikiId = findWikiCatalogListReqDTO.getId();
        // 获取该知识库下所有目录数据
        List<WikiCatalogDO> catalogDOS = wikiCatalogMapper.selectByWikiId(wikiId);
        // DO 转 VO
        List<FindWikiCatalogListRspVO> vos = null;
        if (!CollectionUtils.isEmpty(catalogDOS)) {
            vos = Lists.newArrayList();
            // 过滤出一级目录，并按 sort 值升序排列
            List<WikiCatalogDO> level1Catalogs = catalogDOS.stream()
                    .filter(catalogDO -> Objects.equals(catalogDO.getLevel(), WikiCatalogLevelEnum.ONE.getValue())) // 过滤
                    .sorted(Comparator.comparing(WikiCatalogDO::getSort)) // 升序
                    .collect(Collectors.toList());
            // 构造 VO 对象, 并添加到 vos 集合中
            for (WikiCatalogDO level1Catalog : level1Catalogs) {
                vos.add(FindWikiCatalogListRspVO.builder()
                        .id(level1Catalog.getId())
                        .articleId(level1Catalog.getArticleId())
                        .title(level1Catalog.getTitle())
                        .level(level1Catalog.getLevel())
                        .build());
            }
            // 循环 vos 集合，开始构造二级目录数据
            vos.forEach(level1Catalog -> {
                // 一级目录的 ID
                Long parentId = level1Catalog.getId();
                // 过滤出当前一级目录下的子目录，并按照 sort 值升序排列
                List<WikiCatalogDO> level2CatalogDOS = catalogDOS.stream()
                        .filter(catalogDO -> Objects.equals(catalogDO.getParentId(), parentId)
                                && Objects.equals(catalogDO.getLevel(), WikiCatalogLevelEnum.TWO.getValue()))
                        .sorted(Comparator.comparing(WikiCatalogDO::getSort))
                        .collect(Collectors.toList());
                // 设置子目录数据到 children 字段中
                if (!CollectionUtils.isEmpty(level2CatalogDOS)) {
                    List<FindWikiCatalogListRspVO> level2Catalogs = level2CatalogDOS.stream()
                            .map(catalogDO -> FindWikiCatalogListRspVO.builder()
                                    .id(catalogDO.getId())
                                    .articleId(catalogDO.getArticleId())
                                    .title(catalogDO.getTitle())
                                    .level(catalogDO.getLevel())
                                    .build())
                            .collect(Collectors.toList());
                    level1Catalog.setChildren(level2Catalogs);
                }
            });
        }
        return Result.success(vos);
    }

    @Override
    public Result findArticlePreNext(FindWikiArticlePreNextReqDTO findWikiArticlePreNextReqDTO) {
        // 知识库 ID
        Long wikiId = findWikiArticlePreNextReqDTO.getId();
        // 文章 ID
        Long articleId = findWikiArticlePreNextReqDTO.getArticleId();
        FindWikiArticlePreNextRspVO vo = new FindWikiArticlePreNextRspVO();
        // 获取当前文章所属知识库的目录
        WikiCatalogDO wikiCatalogDO = wikiCatalogMapper.selectByWikiIdAndArticleId(wikiId, articleId);
        // 构建上一篇文章 VO
        WikiCatalogDO preArticleDO = wikiCatalogMapper.selectPreArticle(wikiId, wikiCatalogDO.getId());
        if (Objects.nonNull(preArticleDO)) {
            FindPreNextArticleRspVO preArticleVO = FindPreNextArticleRspVO.builder()
                    .articleId(preArticleDO.getArticleId())
                    .articleTitle(preArticleDO.getTitle())
                    .build();
            vo.setPreArticle(preArticleVO);
        }
        // 构建下一篇文章 VO
        WikiCatalogDO nextArticleDO = wikiCatalogMapper.selectNextArticle(wikiId, wikiCatalogDO.getId());
        if (Objects.nonNull(nextArticleDO)) {
            FindPreNextArticleRspVO nextArticleVO = FindPreNextArticleRspVO.builder()
                    .articleId(nextArticleDO.getArticleId())
                    .articleTitle(nextArticleDO.getTitle())
                    .build();
            vo.setNextArticle(nextArticleVO);
        }
        return Result.success(vo);
    }
}
